package com.neo.repository.impl;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.BulkOperations;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.aggregation.Aggregation;
import org.springframework.data.mongodb.core.aggregation.AggregationResults;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.stereotype.Component;
import java.util.List;

import com.mongodb.BasicDBObject;
import com.mongodb.DBObject;
import com.mongodb.client.result.UpdateResult;
import com.neo.model.AbiCallInfo;
import com.neo.model.AlarmHeadCount;
import com.neo.model.AlarmHeadCountRecordEntity;
import com.neo.model.User;
import com.neo.model.group.PT;
import com.neo.repository.UserRepository;

/**
 * Created by summer on 2017/5/5.
 */
@Component
public class UserRepositoryImpl implements UserRepository {

    @Autowired
    private MongoTemplate mongoTemplate;

    /**
     * 创建对象
     *
     * @param userList
     */
    @Override
    public void saveUser(List<AbiCallInfo> userList) {
        mongoTemplate.bulkOps(BulkOperations.BulkMode.UNORDERED, "tc_cuc_account_balance_record_20190920").insert(userList).execute();
    }

    /**
     * 根据用户名查询对象
     *
     * @param userName
     * @return
     */
    @Override
    public User findUserByUserName(String userName) {
        Query query = new Query(Criteria.where("userName").is(userName));
        User user = mongoTemplate.findOne(query, User.class);
        return user;
    }

    /**
     * 更新对象
     *
     * @param user
     */
    @Override
    public long updateUser(User user) {
        Query query = new Query(Criteria.where("userName").is(user.getUserName()));
        Update update = new Update().set("passWord", user.getPassWord());
        //更新查询返回结果集的第一条
        UpdateResult result = mongoTemplate.updateMulti(query, update, "userInfo");
        return result.getMatchedCount();
    }

    /**
     * 删除对象
     *
     * @param id
     */
    @Override
    public void deleteUserById(Long id) {
        Query query = new Query(Criteria.where("id").is(id));
        mongoTemplate.remove(query, User.class);
    }

    @Override public void saveRecord(List<AlarmHeadCountRecordEntity> userList) {
        mongoTemplate.bulkOps(BulkOperations.BulkMode.UNORDERED, "t_alarm_retention_send").insert(userList).execute();
        //        mongoTemplate.bulkOps(BulkOperations.BulkMode.UNORDERED, "t_alarm_headcount_send").insert(userList).execute();
    }

    @Override public void saveRecord1(List<AlarmHeadCount> userList) {
        mongoTemplate.bulkOps(BulkOperations.BulkMode.UNORDERED, "t_person_headcount_detail").insert(userList).execute();
    }

    @Override public void saveStudentInfo(List<PT> pts) {
        mongoTemplate.bulkOps(BulkOperations.BulkMode.UNORDERED, "student_info").insert(pts).execute();
    }

    /**
     * @Description: 根据年级聚合
     * "统计各个年级人数"   这个比较简单，我们只需要按照年级分组然后进行sum就能得到结果
     * db.pt.aggregate([ { "$group" : { "_id" : "$grade_name" , "总人数" : { "$sum" : 1}}}] )
     * @Return com.mongodb.DBObject
     * @Author liulonglong
     * @Date 2019/11/25 15:39
     **/
    @Override public List<DBObject> groupByGrade(int pageNum, int pageSize) {
        AggregationResults<DBObject> aggregate = mongoTemplate
                .aggregate(Aggregation.newAggregation(Aggregation.group("grade_id").count().as("总人数"), Aggregation.limit(pageSize),
                        Aggregation.skip(Long.valueOf(pageNum - 1) * pageSize)), "student_info", DBObject.class);
        return aggregate.getMappedResults();
    }

    /**
     * @param start 开始
     * @param end   结束范围
     * @Description: "统计某个年级某一项测试在某个范围的人数"  这个也不难，只需要匹配 年级+测试项目+项目分数 between 分数1 and 分数2 然后根据年级分组统计
     * db.pt.aggregate(
     * [ { "$match" : { "grade_name" : "一年级"}} , { "$unwind" : "$items"} ,
     * { "$match" : { "items.item_name" : "BMI" , "items.score" : { "$gt" : 60 , "$lt" : 70}}} , { "$group" : { "_id" : "$grade_name" , "一年级BMI正常人数" : { "$sum" : 1}}}]
     * )
     * unwind : db.inventory.insertOne({ "_id" : 1, "item" : "ABC1", sizes: [ "S", "M", "L"] })
     * db.inventory.aggregate( [ { $unwind : "$sizes" } ] )
     * { "_id" : 1, "item" : "ABC1", "sizes" : "S" }
     * { "_id" : 1, "item" : "ABC1", "sizes" : "M" }
     * { "_id" : 1, "item" : "ABC1", "sizes" : "L" }
     * @Return com.mongodb.DBObject
     * @Author liulonglong
     * @Date 2019/11/25 15:42
     **/
    @Override public List<DBObject> groupByGradeAndGetCountBetweenRange(double start, double end, int pageNum, int pageSize) {
        AggregationResults<DBObject> aggregate = mongoTemplate
                .aggregate(Aggregation.newAggregation(
                        // unwind 将文档中的某一个数组类型字段拆分成多条，每条包含数组中的一个值。
                        Aggregation.unwind("items"),
                        // 匹配（过滤）$match：用于过滤数据，只输出符合条件的文档。$match使用MongoDB的标准查询操作。
                        Aggregation.match(Criteria.where("items.item_name").is("身高").and("items.score").lt(end).gt(start)),
                        // 分组操作GroupOperation
                        Aggregation.group("grade_name").count().as("身高合格人数"),
                        // 分页操作LimitOperation
                        Aggregation.limit(pageSize),
                        // // 分页操作SkipOperation
                        Aggregation.skip(Long.valueOf(pageNum - 1) * pageSize)), "student_info", DBObject.class);
        // 其它 $project：修改输入文档的结构。可以用来重命名、增加或删除域，也可以用于创建计算结果以及嵌套文档。
        // $sort：将输入文档排序后输出。
        return aggregate.getMappedResults();
    }

    /**
     * @param start    开始
     * @param end      结束范围
     * @param pageNum
     * @param pageSize
     * @Description: "统计某个年级某一项测试在不在某个范围的人数"  这个也不难，只需要匹配 年级+测试项目+项目分数 between 分数1 and 分数2 然后根据年级分组统计
     * @Return com.mongodb.DBObject
     * @Author liulonglong
     * @Date 2019/11/25 15:42
     **/
    @Override public List<DBObject> groupByGradeAndGetCountNotBetweenRange(double start, double end, int pageNum, int pageSize) {
        AggregationResults<DBObject> aggregate = mongoTemplate
                .aggregate(Aggregation.newAggregation(
                        // unwind 将文档中的某一个数组类型字段拆分成多条，每条包含数组中的一个值。
                        Aggregation.unwind("items"),
                        // 匹配（过滤）$match：用于过滤数据，只输出符合条件的文档。$match使用MongoDB的标准查询操作。
                        Aggregation.match(Criteria.where("items.item_name").is("身高")
                                .orOperator(Criteria.where("items.score").lte(start), Criteria.where("items.score").gte(end))),
                        // 分组操作GroupOperation
                        Aggregation.group("grade_name").count().as("身高不合格人数"),
                        // 分页操作LimitOperation
                        Aggregation.limit(pageSize),
                        // // 分页操作SkipOperation
                        Aggregation.skip(Long.valueOf(pageNum - 1) * pageSize)), "student_info", DBObject.class);
        // 其它 $project：修改输入文档的结构。可以用来重命名、增加或删除域，也可以用于创建计算结果以及嵌套文档。
        // $sort：将输入文档排序后输出。
        return aggregate.getMappedResults();
    }

    /**
     * @param pageNum
     * @param pageSize
     * @Description:统计各个测试项目得分的最大值，最小值，平均值” 这个问题其实就是针对测试项目进行分组，然后使用 min max avg函数
     * mongo ：
     * db.pt.aggregate(
     * [ { "$match" : { "grade_name" : "一年级"}} , { "$unwind" : "$items"} , { "$group" : { "_id" : "$items.item_name" , "平均分" : { "$avg" : "$items.score"} , "最小值" : { "$min" : "$items.score"} , "最大值" : { "$max" : "$items.score"}}}]
     * )
     * @Return java.util.List<com.mongodb.BasicDBObject>
     * @Author liulonglong
     * @Date 2019/11/26 10:16
     **/
    @Override public List<BasicDBObject> stat(int pageNum, int pageSize) {
        Aggregation aggregation = Aggregation.newAggregation(
                Aggregation.match(Criteria.where("grade_name").is("一年级")),

                Aggregation.unwind("items"),

                Aggregation.group("$items.item_name").avg("$items.score").as("平均分").
                        min("$items.score").as("最小值").
                        max("$items.score").as("最大值"),
                // 分页操作LimitOperation
                Aggregation.limit(pageSize),
                // // 分页操作SkipOperation
                Aggregation.skip(Long.valueOf(pageNum - 1) * pageSize));
        AggregationResults<BasicDBObject> student_info = mongoTemplate.aggregate(aggregation, "student_info", BasicDBObject.class);
        return student_info.getMappedResults();
    }
}
